package com.lb.sssq.service.imp;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.edais.dao.CenterDao;
import com.edais.dao.PayDao;
import com.edais.domain.Bank;
import com.edais.domain.OrderFormRecharge;
import com.edais.domain.PayDataBean;
import com.edais.domain.RetBean;
import com.edais.domain.User;
import com.edais.domain.UserInfo;
import com.edais.domain.zftPay.PayParamtersTemp;
import com.edais.service.CenterService;
import com.edais.service.UserService;
import com.edais.util.LianlianPayUtil;
import com.edais.util.ThirdPartyEnvUtil;
import com.edais.util.RSAThirdParty.RSA;
import com.edais.vo.UserBankCardVo;
import com.lb.sssq.service.SssqPayService;
import com.lb.sssq.util.CommonUtil;
import com.lb.sssq.util.Consts;
import com.lb.sssq.util.JsonUtil;
import com.lb.sssq.util.LLPayHostingEnvUtil;
import com.lb.sssq.util.Message;

@Service

@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class SssqPayServiceImp implements SssqPayService {
	private static final Log logger = LogFactory.getLog(SssqPayServiceImp.class);

	@Autowired
	private CenterService centerService;

	@Autowired
	private UserService userService;
	
	@Autowired
	private CenterDao centerDao;
	
	@Autowired
	private PayDao payDao;

	@Override
	public Map<String, Object> doPost(HttpServletRequest req,
			HttpServletResponse resp) throws Exception {
		logger.debug("进入连连支付异步通知数据接收处理");
		HashMap<String, Object> map = new HashMap<String, Object>();
		resp.setCharacterEncoding("UTF-8");
		RetBean retBean = new RetBean();
		String reqStr = LianlianPayUtil.readReqStr(req);
		if (StringUtils.isBlank(reqStr)) {
			logger.debug("解析支付异步通知数据失败");
			retBean.setRet_code("9999");
			retBean.setRet_msg("交易失败");
			resp.getWriter().write(JSON.toJSONString(retBean));
			resp.getWriter().flush();
			map.put("result", false);
			return map;
		}
		logger.debug("接收支付异步通知数据：【" + reqStr + "】");
		try {
			if (!LianlianPayUtil.checkSign(reqStr,
					LLPayHostingEnvUtil.getValue("yt_pub_key"),
					LLPayHostingEnvUtil.getValue("md5_key"))) {
				retBean.setRet_code("9999");
				retBean.setRet_msg("交易失败");
				resp.getWriter().write(JSON.toJSONString(retBean));
				resp.getWriter().flush();
				logger.debug("支付异步通知验签失败");
				map.put("result", false);
				return map;
			}
		} catch (Exception e) {
			logger.debug("异步通知报文解析异常：" + e);
			retBean.setRet_code("9999");
			retBean.setRet_msg("交易失败");
			resp.getWriter().write(JSON.toJSONString(retBean));
			resp.getWriter().flush();
			map.put("result", false);
			return map;
		}
		retBean.setRet_code("0000");
		retBean.setRet_msg("交易成功");
		resp.getWriter().write(JSON.toJSONString(retBean));
		resp.getWriter().flush();
		logger.debug("支付异步通知数据接收处理成功");
		// 解析异步通知对象
		PayDataBean payDataBean = JSON.parseObject(reqStr, PayDataBean.class);
		map.put("result", true);
		map.put("reqStr", reqStr);
		map.put("payDataBean", payDataBean);
		return map;
	}

	/**
	 * 获取支付临时参数(new)
	 */
	@Override
	public PayParamtersTemp getTmpPayParameter(String orderId) throws Exception {
//		return payDao.getTmpPayParameter(orderId);
		return null;
	}

	/**
	 * 充值预下单参数检查
	 * @return
	 * @throws Exception
	 */
	@Override
	public Map<String,String> checkRechargeParam(Map<String, String> map) throws Exception {
		Map<String, String> result = new HashMap<String, String>();
		
		// 用户id
		String userId = map.get("userId");
		// 绑定银行卡id
		String backCardId = map.get("backCardId");
		// 充值金额(元)
		String cardAmountStr = map.get("rechargeAmount");
		
		// 程序必须参数未传入
		if (StringUtils.isBlank(userId)
				|| StringUtils.isBlank(backCardId)) {
			result.put("code", Consts.ERROR_CODE);
			result.put("message",
					Message.CnDescriptionExpression.BUSINESSE_ERROR);
			return result;
		}

		// 充值金额未输入
		if (StringUtils.isBlank(cardAmountStr)) {
			result.put("code", Consts.CHECK_CODE);
			result.put("message",
					Message.CnDescriptionExpression.BUYAMOUNT_IS_LESSTHAN_1YUAN);
			return result;
		}

		// 充值金额检查（必须是1元以上）
		boolean flag = cardAmountStr.matches("^[0-9]*[\\.]{0,1}[0-9]{0,2}$");
		if (!flag) {
			// 输入的值为非法字符
			result.put("code", Consts.CHECK_CODE);
			result.put("message",
					Message.CnDescriptionExpression.MOUNT_IS_NON_STANDARD);
			return result;
		}

		// 判断用户是否实名认证
		User user = userService.getUserDetail(userId);
		if (!"1".equals(user.getIs_create_acct())
				|| !"Y".equals(user.getIdcard_validate())) {
			// 没有经过实名认证不能进行购买
			result.put("code", Consts.CHECK_CODE);
			result.put("message",Message.CnDescriptionExpression.AUTHENTICATION_IS_NOT);
			return result;
		}

		/**
		 * 根据用户选择的银行卡获取支付渠道，如果是支付通则需要对充值金额进行1.01大小的判断
		 */
		HashMap<String,Object> userPayCdParam = new HashMap<String,Object>();
		userPayCdParam.put("isValid","Y");
		userPayCdParam.put("bankCardId", backCardId);
		userPayCdParam.put("userId", userId);
		userPayCdParam.put("isBinding", "Y");
		UserBankCardVo userRecePayCard =centerService.getRecePayBank(userPayCdParam);
		if(null == userRecePayCard){
			logger.error("快捷支付预下单（仅充值）初期数据检查发生异常：用户银行信息不存在");
			result.put("code", Consts.ERROR_CODE);
			result.put("message",
					Message.CnDescriptionExpression.BUSINESSE_ERROR);
			return result;
		}
		
		HashMap<String,String> payPlatParam = new HashMap<String,String>();
		payPlatParam.put("bankId", userRecePayCard.getBank_id());
		
		Bank bank = getPayPlatformById(payPlatParam);
		BigDecimal amount = new BigDecimal(cardAmountStr);//充值金额（元）
		
		if(bank != null && "LIANLIANPAY".equalsIgnoreCase(bank.getPlatform_en_name())){
			String amount_fen = amount.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
			map.put("txAmt", amount_fen);//充值金额（元）
			map.put("platform_name", "LIANLIANPAY");//平台名称
			map.put("platform_id", bank.getBank_code());
		}else{
			logger.error("快捷支付预下单初期数据检查（仅充值）发生异常：银行对应的平台不存在。支付平台=" + bank.getPlatform_en_name());
			result.put("code", Consts.ERROR_CODE);
			result.put("message",
					Message.CnDescriptionExpression.BUSINESSE_ERROR);
			return result;
		}
		
		result.put("code", Consts.SUCCESS_CODE);
		result.put("message", Consts.SUCCESS_DESCRIBE);
		return result;
	}
	
	/**
	 * 根据选择的银行卡选择对应的支付平台
	 */
	@Override
	public Bank getPayPlatformById(Map<String, String> map) throws Exception {
		return payDao.getPayPlatformById(map);
	}
	
	/**
	 * 快捷支付预下单主业务处理（仅充值）
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false)
	public Map<String,String> dealRechargeToken(Map<String, String> map) throws Exception {
		Map<String,String> resMap = new HashMap<String,String>();
		
		// 充值
		resMap = doRecharge(map);
		
		if(!Consts.SUCCESS_CODE.equals(resMap.get("code"))){
			return resMap;
		}
		
		// 保存临时参数
		addRechargeTokenParamters(map);

		/*resMap.put("orderId", resMap.get("orderId"));
		resMap.put("contentPay", resMap.get("contentPay"));
		
		resMap.put("code", Consts.SUCCESS_CODE);
		resMap.put("message", Consts.SUCCESS_DESCRIBE);*/
		return resMap;
	}
	
	/**
	 * 第三方充值请求
	 * @throws Exception
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false)
	public Map<String,String> doRecharge(Map<String, String> map) throws Exception {
		Map<String,String> resMap = new HashMap<String,String>();
		
		// 用户id
		String userId = map.get("userId");
		// 银行卡id
		String backCardId = map.get("backCardId");
		// 充值金额（支付通是以分为单位，连连支付是以元为单位）
		String amountFen = map.get("txAmt");
		// 充值金额(元)
		String rechargeAmount = map.get("rechargeAmount");
		
		String buyFlag = map.get("buyFlag");
		
		// 获取交易流水号
		String orderId = centerService.setSeqCycleOrderNo();
		logger.debug("支付预下单请求订单号：" + orderId);
		// 获取身份信息
		UserInfo userInfo = userService.getUserInfo(userId);
		// 根据银行卡id取得用户的银行卡信息
		HashMap<String,Object> userPayCdParam = new HashMap<String,Object>();
		userPayCdParam.put("isValid","Y");
		userPayCdParam.put("bankCardId", backCardId);
		userPayCdParam.put("userId", userId);
		userPayCdParam.put("isBinding", "Y");
		UserBankCardVo userRecePayCard =centerService.getRecePayBank(userPayCdParam);
		
		// 交易时间
		SimpleDateFormat dataFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		Date date = new Date();
		String timeString = dataFormat.format(date);

		Map<String, String> payParamMap = new HashMap<String, String>();
		String url = "";
		String merNo  = "";
		if("LIANLIANPAY".equalsIgnoreCase(map.get("platform_name"))){
			// 连连支付
			String notify_url = "";
			//第三方工程请求url
			if("N".equals(buyFlag)){
				// 充值回调地址
				notify_url = LLPayHostingEnvUtil.getValue("lianlianPayUrl_R");
				logger.debug("连连支付充值回调url：" + notify_url);
			}else{
				// 购买回调地址
				notify_url = LLPayHostingEnvUtil.getValue("lianlianPayUrl_B");
				logger.debug("连连支付购买回调url：" + notify_url);
			}
			
			// 请求参数封装
			payParamMap.put("userId", userId);
			payParamMap.put("orderId", orderId);
			payParamMap.put("sum", amountFen);
			payParamMap.put("notifyUrl", notify_url);
			payParamMap.put("fullName",userInfo.getReal_name());
			payParamMap.put("idNo", userInfo.getId_card());
			payParamMap.put("cardNo", userRecePayCard.getCard_number());
			
			//第三方工程请求url
			url = ThirdPartyEnvUtil.getValue("lianlianPayTokenUrl");
			logger.debug("连连支付请求第三方工程url：" + url);
			merNo = LLPayHostingEnvUtil.getValue("lianlian_partner_id");//商户号
		}else{
			logger.error("快捷支付预下单发生异常：银行对应的平台不存在。支付平台=" + map.get("platform_name"));
			throw new RuntimeException("充值预下单失败");
		}

		String requestParam = "keyRandom=KEY_RANDOM";
		String publicKeyParam="";
		try {
			publicKeyParam = RSA.getPublick_Key_Encrypt(payParamMap);
			requestParam = requestParam.replace("KEY_RANDOM", URLEncoder.encode(publicKeyParam, "utf-8"));
		} catch (Exception e) {
			logger.debug("公钥加密串："+e);
		}

		String paramStr = "";
		String fastPayToken = "";
		String platform = "";
		
		String payTokenResult = CommonUtil.sendPostByHttp(url, requestParam);
		if( null == payTokenResult ){
			logger.error("充值_预下单失败");
			throw new RuntimeException("充值预下单失败");
		}else{
			//解析发送结果
			Map payTokenResultMap = JsonUtil.getMapFromJsonString(payTokenResult);
			if(null == payTokenResultMap  || "sysException".equals(payTokenResultMap.get("rescode"))){
				// 系统异常
				logger.error("充值_预下单失败:" + String.valueOf(payTokenResultMap.get("resmsg_cn")));
				resMap.put("code", Consts.CHECK_CODE);
				resMap.put("message", "充值预下单失败");
				return resMap;
			}else if("BusinessException".equals(payTokenResultMap.get("rescode"))){
				// 业务异常，把错误信息提示给用户
				logger.error("充值_预下单失败:" + String.valueOf(payTokenResultMap.get("resmsg_cn")));
				resMap.put("code", Consts.CHECK_CODE);
				resMap.put("message", String.valueOf(payTokenResultMap.get("resmsg_cn")));
				return resMap;
			}else{
				if("LIANLIANPAY".equalsIgnoreCase(map.get("platform_name"))){
					paramStr = String.valueOf(payTokenResultMap.get("contentPay"));
					logger.debug("连连预下单请求参数：" + paramStr);
					platform = "LIANLIANPAY";
				}
			}
		}
		
		map.put("orderId", orderId);
		map.put("merNo", merNo);
		map.put("timeString", timeString);
		map.put("fastPayToken", fastPayToken);
		
		// 充值订单生成
		OrderFormRecharge orderFormRecharge = new OrderFormRecharge();
		orderFormRecharge.setAmount(new BigDecimal(rechargeAmount));// 订单金额（元）
		orderFormRecharge.setOrderform_id(orderId);// 订单号
		orderFormRecharge.setRecharge_orderform_status("WAIT_BUYER_PAY");// 等待付款
		orderFormRecharge.setUser_id(Integer.parseInt(userId));// 所属用户
		orderFormRecharge.setSend_message(paramStr);// 上送报文
		orderFormRecharge.setRechargetype("01");// 理财人类型
		orderFormRecharge.setAccounttype("01");// 个人主账户
		orderFormRecharge.setCore_status("CORE_WAIT");// 未调用核心，初始化状态
		orderFormRecharge.setRecharge_channel("MOBILE"); //充值渠道（WEB:网站;MOBILE:移动端）
		orderFormRecharge.setRecharge_platform(map.get("platform_id"));//充值平台（UPAY:U付;SINAPAY:新浪支付;LIANLIANPAY:连连支付）
//		orderFormRecharge.setSelectbank(userRecePayCard.getYlbankcode());
		centerDao.createRechargeOrder(orderFormRecharge);
		
		resMap.put("orderId", orderId);
		resMap.put("contentPay", paramStr);
		resMap.put("code", Consts.SUCCESS_CODE);
		resMap.put("message", Consts.SUCCESS_DESCRIBE);
		return resMap;
	}

	/**
	 * 充值临时参数保存
	 * @throws Exception
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false)
	public void addRechargeTokenParamters(Map<String, String> map) throws Exception {
		
		// 购买参数表设置
	    Map<String,String> rechargeParamMap = new HashMap<String,String>();
	    rechargeParamMap.put("tradeOrderId", map.get("orderId"));// 流水号,不可重复
	    rechargeParamMap.put("merNo", map.get("merNo"));// 支付通提供商户号
	    rechargeParamMap.put("trDt", map.get("timeString"));// 交易时间 yyyyMMddhhmmss
	    rechargeParamMap.put("fastPayToken", map.get("fastPayToken"));//平台验证码
	    rechargeParamMap.put("rechargeAmount", map.get("rechargeAmount"));//充值金额
	    rechargeParamMap.put("platform_id", map.get("platform_id"));//支付平台id
	    rechargeParamMap.put("pay_card_id", map.get("backCardId"));//回款银行卡号表id
	    rechargeParamMap.put("userId", map.get("userId"));//用户id
	    
		String paramterJson = JsonUtil.getJsonStringFromMap(rechargeParamMap);
		
		PayParamtersTemp paramtersBean = new PayParamtersTemp();
		paramtersBean.setCreate_per(map.get("userId"));
		paramtersBean.setParameter_str(paramterJson);
		paramtersBean.setPlatform_en_name(map.get("platform_name"));
		paramtersBean.setReq_orderid(map.get("orderId"));
		paramtersBean.setUpdate_per(map.get("userId"));
		payDao.addPayParameter(paramtersBean);
	}
}
